<?php
	/**
	 *	KLF Framework
	 *
	 *	Written by Kristian Oye <kristianoye@gmail.com> on Oct 23, 2011
	 *	Copyright (C) 2010-2011
	 */
	namespace KLF\System
	{
		/**
		 *  Class KDateTime
		 *
		 *  Wrapper for the standard PHP DateTime class
		 *
		 *  @package KLF\System
		 *  @access public
		 *  @author Kristian Oye <kristianoye@gmail.com>
		 *  @since 0.1
		 *  
		 *  @method KDateTime NewInstance
		 *  
		 *  @property DateTime $DateTime The internal representation of the KDateTime object.
		 */
		use KLF\KCore;

		use KLF\System\Errors\KArgumentException;

		class KDateTime extends KObject
		{
			/**
			 * Internal representation of DateTime
			 * @var \DateTime
			 */
			protected $_propDateTime;
			
			/**
			 * Constructs a new KDateTime object
			 * @param int|string $dateTimeIn Can either be a string or a UNIX timestamp.
			 * @param \DateTimeZone $tzInfo
			 */
			public function __construct($dateTimeIn = NULL, \DateTimeZone $tzInfo = NULL)
			{
				if (!isset($dateTimeIn) && !isset($tzInfo))
				{
					$this->_propDateTime = new \DateTime();
				}
				else if(is_int($dateTimeIn))
				{
					$this->_propDateTime = new \DateTime();
					$this->_propDateTime->setTimestamp($dateTimeIn);
				}
				else 
				{
					$this->_propDateTime = new \DateTime($dateTimeIn, $tzInfo);
				}
			}
			
			/**
			 * Adds an interval to the DateTime.
			 * 
			 * @param \DateInterval $intv
			 * @return DateTime|\KLF\System\KDateTime
			 */
			public function AddInterval(\DateInterval $intv)
			{
				return $this->_propDateTime->add($intv);
				return $this;
			}
			
			/**
			 * Adds a number of days to the DateTime
			 * 
			 * @param int $n
			 * @throws KArgumentException
			 * @return \KLF\System\KDateTime
			 */
			public function AddDays($n = 0)
			{
				if (!is_int($n))
					throw new KArgumentException("Bad argument 1 to KDateTime::AddDays()");
				if($n < 0)
					$this->_propDateTime->sub(new \DateInterval('P'.(-$n).'D'));
				else
					$this->_propDateTime->add(new \DateInterval('P'.$n.'D'));
				return $this;
			}
			

			/**
			 * Adds a number of hours to the DateTime
			 * 
			 * @param int $n
			 * @throws KArgumentException
			 * @return \KLF\System\KDateTime
			 */
			public function AddHours($n = 0)
			{
				if (!is_int($n))
					throw new KArgumentException("Bad argument 1 to KDateTime::AddHours()");
				if($n < 0)
					$this->_propDateTime->sub(new \DateInterval('PT'.(-$n).'H'));
				else
					$this->_propDateTime->add(new \DateInterval('PT'.$n.'H'));
				return $this;
			}

			/**
			 * Adds a number of minutes to the DateTime
			 * 
			 * @param int $n
			 * @throws KArgumentException
			 * @return \KLF\System\KDateTime
			 */
			public function AddMinutes($n = 0)
			{
				if (!is_int($n))
					throw new KArgumentException("Bad argument 1 to KDateTime::AddMinutes()");

				if($n < 0)
					$this->_propDateTime->sub(new \DateInterval('PT'.(-$n).'M'));
				else
					$this->_propDateTime->add(new \DateInterval('PT'.$n.'M'));
				
				return $this;
			}
			
			/**
			 * Adds a number of months to the DateTime
			 * 
			 * @param int $n
			 * @throws KArgumentException
			 * @return \KLF\System\KDateTime
			 */
			public function AddMonths($n = 0)
			{
				if (!is_int($n))
					throw new KArgumentException("Bad argument 1 to KDateTime::AddMonths()");
				
				if($n < 0)
					$this->_propDateTime->sub(new \DateInterval('P'.(-$n).'M'));
				else
					$this->_propDateTime->add(new \DateInterval('P'.$n.'M'));

				return $this;
			}
			
			
			/**
			 * Adds a number of minutes to the DateTime
			 * 
			 * @param int $n
			 * @throws KArgumentException
			 * @return \KLF\System\KDateTime
			 */
			public function AddSeconds($n = 0)
			{
				if (!is_int($n))
					throw new KArgumentException("Bad argument 1 to KDateTime::AddSeconds()");
				if($n < 0)
					$this->_propDateTime->sub(new \DateInterval('PT'.(-$n).'S'));
				else
					$this->_propDateTime->add(new \DateInterval('PT'.$n.'S'));
								
				return $this;
			}
			
			/**
			 * Adds or subtracts a number of years from the DateTime
			 * 
			 * @param int $n
			 * @throws KArgumentException
			 * @return \KLF\System\KDateTime
			 */
			public function AddYears($n = 0)
			{
				if (!is_int($n))
				throw new KArgumentException("Bad argument 1 to KDateTime::AddYears()");
				
				if($n < 0)
					$this->_propDateTime->sub(new \DateInterval('P'.(-$n).'Y'));
				else
					$this->_propDateTime->add(new \DateInterval('P'.$n.'Y'));
								
				return $this;
			}
			
			/**
			 * (non-PHPdoc)
			 * @see KLF\System.KObject::__toString()
			 */
			public function __toString()
			{
				return $this->_propDateTime->format('Y-m-d H:i:s');
			}
			
			/**
			 * Try and parse a string as KDateTime object.  Returns false if
			 * the date could not be parsed.
			 * 
			 * @param string $input
			 * @return boolean|KDateTime
			 */
			public static function TryParse($input, $errorOnFailure = false)
			{
				try
				{
					$ret = new KDateTime($input);
				}
				catch(\Exception $ex)
				{
					if ($errorOnFailure)
					{
						throw new KArgumentException(
							KCore::FS("DateTime::TryParse() could not convert '{val}' into a DatTime.",
								array('val' => $input)));
					}
					$ret = false;
				}
				return $ret;
			}
		}
	}